在過去 15 天的分享,我們把關注點放在變數、函式等細節上,但除了細節,要能夠寫出真正整潔的程式碼,我們還必須要在更高層次的部分付出心力。今天我們將來談談關於類別的基礎概念。
遵循標準 Java 的慣例,類別的開頭依序是:一連串變數、公用靜態常數、私有靜態變數、私有實體變數。至於公用變數,通常情況下我們不會有什麼好的理由,會在類別當中使用到這類變數。
變數宣告後會緊接著公用函式,並照著我們先前所提過的「降層法則」,讓讀者能夠輕易明白類別的內部。
值得一提的是,在 OOP 模式中我們會對類別進行封裝,並希望變數及工具函式能保持私有 (private) 狀態,但對此作者並不執著。有時會讓它們是保護 (protected) 型態,原因是這樣測試程式才能夠存取它們。
測試即王道,但我們仍會盡力保持其私有性,非不得已時才會放寬封裝的限制。
我們在之前曾強調過函式必須要簡短,而類別需要簡短的重要性,就與函式一樣,這幾乎就是它們的根本。那麼與函式相同地,我們也需要問,怎樣的類別算是簡短呢?
在函式的範疇裡,我們會用行數、用內部包含的抽象概念去衡量;而在類別中,我們則會計算它職責的數量。一個包含七十個方法的類別,大多數人會同意說它太大了,甚至某些開發者會稱其為「神的類別」,那麼五個方法呢?
public class SuperDashboard extends JFrame implements MetaDataUser {
public Component getLastFocusedComponent()
public void setLastFocused()
public int getMajorVersionNumber()
public int getMinorVersionNumber()
public int getBuildNumber()
}
在上面的例子中,方法並不多,但它仍然包含太多的職責。
經過前面關於函式的學習,我們能很快速地理解,類別的名稱要能夠描述其職責。當類別名稱無法簡單、明確地去表示該類別的職責,那可能就代表這個類別已經過大;如果名稱過於模糊,那很可能這個類別職責過多。
當我們提到類別、提到職責,就不得不說大名鼎鼎的單一職責原則(Single Responsibility Principle, SRP)。
單一職責原則主張:一個類別或一個模組應該有一個,且只能有一個修改的理由。這個原則提供了關於類別職責與大小的建構方針────唯一一個修改的理由。
回到上面的程式碼,我們可以發現,在 SuperDashboard 的類別中,看起來有兩個修改的理由:
所以依循單一職責原則,我們會對該類別進行重構,將不同職責的類別分離出來:
public class Version {
public int getMajorVersionNumber()
public int getMinorVersionNumber()
public int getBuildNumber()
}
將不同的職責分離出來成為不同的類別,就如同我們將不同概念的函式分開一般,它能夠避免我們在維護程式的時候,花上大把精力在理解我們不需要了解的部分,也避免我們改動到我們不應該改動到的程式碼。